home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / EnterAct Stuff / Drag_on Modules / hAWK example progs / $FuncTree < prev    next >
Text File  |  1994-01-26  |  7KB  |  379 lines

  1. # $FuncTree : on a per-file basis, print a list of function definitions
  2. # as encountered, and for each defined function print a list of functions
  3. # called by the defined function. 
  4. # -this was written to prototype EnterAct's function call/caller tree indexer.
  5.  
  6.  
  7. BEGIN {
  8.     init_lexer();
  9.     first_time = 1
  10.     }
  11.  
  12. FNR == 1 {
  13.     z = split(ARGV[1], names, ":")
  14.     filename = names[z];
  15.  
  16.     curlyCount = 0
  17.     numCalls = 0
  18.     numDefs = 0
  19.     current_function = ""
  20.     could_be_definition = 0
  21.     toktype = ILLEGAL
  22.     line = $0
  23.     if (first_time != 1)
  24.         init_arrays();
  25.     collect_functions();
  26.     print_names();
  27.     first_time = 0
  28.     }
  29.  
  30. ##END { print_names(); }
  31.  
  32. function init_arrays(    k)
  33.     {
  34.     for (k in func_not_printed)
  35.         delete func_not_printed[k];
  36.     for (k in func_defs)
  37.         delete func_defs[k];
  38.     for (k in func_tree)
  39.         delete func_tree[k];
  40.     }
  41.  
  42. function collect_functions(        type)
  43.     {
  44.     advance();
  45.     while (toktype != EOF)
  46.         {
  47.         if (toktype == NAME)
  48.             {
  49.             type = lookup(tok) # see hAWK User’s Manual 2114 or so
  50.             if (type == 4)
  51.                 {
  52.                 ##funcs[tok]++
  53.                 record_function()
  54.                 }
  55.             }
  56.         else if (toktype == "{")
  57.             {
  58.             ++curlyCount;
  59.             if (could_be_definition == 1 && curlyCount == 1)
  60.                 {
  61.                 func_defs[++numDefs] = current_function
  62.                 func_not_printed[current_function] = 1
  63.                 func_tree[current_function, ++numCalls] = "T";
  64.                 }
  65.             }
  66.         else if (toktype == "}")
  67.             {
  68.             --curlyCount;
  69.             if (curlyCount == 0) # outside a function
  70.                 {
  71.                 current_function = "";
  72.                 could_be_definition = 0;
  73.                 }
  74.             }
  75.         else if (curlyCount == 0 && could_be_definition == 1 && toktype == ";")
  76.             could_be_definition = 0;
  77.         advance();
  78.         }
  79.     }
  80.  
  81. function record_function()
  82.     {
  83.     if (curlyCount == 0) # top level - NOTE could be a prototype for the func
  84.         {
  85.         current_function = tok
  86.         numCalls = 0
  87.         could_be_definition = 1
  88.         }
  89.     else if (current_function != "") # inside a function(?)
  90.         {
  91.         func_tree[current_function, ++numCalls] = tok
  92.         }
  93.     }
  94.  
  95. # For each function definition in the file, in order of occurrence,
  96. # print a list of called functions, also in order of occurrence.
  97. # Only functions which actually call another function are listed,
  98. # and duplicates are suppressed in the call list.
  99. function print_names(    i, j, k, fn)
  100.     {
  101.     for (i = 1; i <= numDefs; ++i)
  102.         {
  103.         fn = func_defs[i]
  104.         if (((fn, 1) in func_tree) \
  105.             && func_not_printed[fn]) # not a spurious mention, not done yet
  106.             {
  107.             func_not_printed[fn] = 0
  108.             for (k in seen)
  109.                 delete seen[k];
  110.             print fn, ":"
  111.             j = 2; # 1 is just to show function is defined
  112.             while ((fn, j) in func_tree)
  113.                 {
  114.                 tok = func_tree[fn, j]
  115.                 if (!(tok in seen))
  116.                     {
  117.                     print "\t", tok
  118.                     seen[tok] = 1
  119.                     }
  120.                 ++j;
  121.                 }
  122.             }
  123.         }
  124.     }
  125.  
  126. function init_lexer()
  127.     {
  128.     NAME = 256
  129.     STRING = 257
  130.     CHAR_CONSTANT = 258
  131.     NUMBER = 259
  132.     KEY = 260
  133.     BITASSIGNOP = 261
  134.     ASSIGNOP = 262
  135.     LEX_OR = 263
  136.     LEX_AND = 264
  137.     RELOP = 265
  138.     SHIFT = 266
  139.     INCREMENT = 267
  140.     DECREMENT = 268
  141.     POINTER = 269
  142.     OTHER = 270
  143.     EOF = 271
  144.     ILLEGAL = 272
  145.     
  146.     C_KEY["..."] = 1
  147.     C_KEY["asm"] = 1
  148.     C_KEY["auto"] = 1
  149.     C_KEY["break"] = 1
  150.     C_KEY["case"] = 1
  151.     C_KEY["char"] = 1
  152.     C_KEY["class"] = 1
  153.     C_KEY["const"] = 1
  154.     C_KEY["continue"] = 1
  155.     C_KEY["default"] = 1
  156.     C_KEY["delete"] = 1
  157.     C_KEY["do"] = 1
  158.     C_KEY["double"] = 1
  159.     C_KEY["else"] = 1
  160.     C_KEY["enum"] = 1
  161.     C_KEY["extern"] = 1
  162.     C_KEY["float"] = 1
  163.     C_KEY["for"] = 1
  164.     C_KEY["goto"] = 1
  165.     C_KEY["if"] = 1
  166.     C_KEY["int"] = 1
  167.     C_KEY["long"] = 1
  168.     C_KEY["new"] = 1
  169.     C_KEY["Pascal"] = 1
  170.     C_KEY["pascal"] = 1
  171.     C_KEY["register"] = 1
  172.     C_KEY["return"] = 1
  173.     C_KEY["short"] = 1
  174.     C_KEY["signed"] = 1
  175.     C_KEY["sizeof"] = 1
  176.     C_KEY["static"] = 1
  177.     C_KEY["struct"] = 1
  178.     C_KEY["switch"] = 1
  179.     C_KEY["typedef"] = 1
  180.     C_KEY["union"] = 1
  181.     C_KEY["unsigned"] = 1
  182.     C_KEY["virtual"] = 1
  183.     C_KEY["void"] = 1
  184.     C_KEY["volatile"] = 1
  185.     C_KEY["while"] = 1
  186.     }
  187.  
  188. function advance()
  189.     {
  190.     if (toktype == EOF) return
  191.     if (tok == "." || tok == "->") #member coming, not a local
  192.         {
  193.         if (match(line, /^[A-Za-z_](\w|_)*/))
  194.             {
  195.             tok = substr(line, 1, RLENGTH)
  196.             line = substr(line, RLENGTH+1)
  197.             toktype = OTHER
  198.             return
  199.             }
  200.         else
  201.             error("missing member name")
  202.         }
  203.     toktype = ILLEGAL
  204.     skip_comments_etc()
  205.     if (toktype == EOF || toktype == STRING || toktype == CHAR_CONSTANT)
  206.         return
  207.     if (match(line, /^[A-Za-z_](\w|_)*/) ||
  208.         match(line, /^\.\.\./)) #name or key - note "..." treated as key.
  209.         {
  210.         tok = substr(line, 1, RLENGTH)
  211.         line = substr(line, RLENGTH+1)
  212.         if (tok in C_KEY)
  213.             toktype = KEY
  214.         else
  215.             toktype = NAME
  216.         return
  217.         }
  218.     if (match(line, /^([0-9]+\.?[0-9]*|\.[0-9]+)([eE][+-]?[0-9]+)?[fFlL]?/) ||
  219.         match(line, /^0[0-7]+(u|U)?(l|L)?/) ||
  220.         match(line, /^0(x|X)[0-9a-fA-F]+(u|U)?(l|L)?/))    #float or int
  221.         toktype = NUMBER;
  222.     else if (match(line, /^(<<=|>>=|&=|\^=|\|=)/))        #bit assign
  223.         toktype = BITASSIGNOP
  224.     else if (match(line, /^(\+=|-=|\*=|\/=|%=)/))        #assign, inc
  225.         toktype = ASSIGNOP
  226.     else if (match(line, /^\|\|/))
  227.         toktype = LEX_OR
  228.     else if (match(line, /^&&/))
  229.         toktype = LEX_AND
  230.     else if (match(line, /^(<=|==|!=|>=)/))                #relational
  231.         toktype = RELOP
  232.     else if (match(line, /^(<<|>>)/))                    #shift
  233.         toktype = SHIFT
  234.     else if (match(line, /^\+\+/))
  235.         toktype = INCREMENT
  236.     else if (match(line, /^--/))
  237.         toktype = DECREMENT
  238.     else if (match(line, /^->/))
  239.         toktype = POINTER
  240.     else if (match(line, /^./))                            #everything else
  241.         {
  242.         #TO DO trap illegal tokens, eg "@"
  243.         toktype = substr(line,1,1)
  244.         }
  245.     else
  246.         error("Unexpected empty line")
  247.     tok = substr(line, 1, RLENGTH)
  248.     line = substr(line, RLENGTH+1)
  249.     }
  250.  
  251. function skip_comments_etc()
  252.     {
  253.     do
  254.         {
  255.         sub(/^[ \t]+/, "", line) #remove leading blanks and tabs
  256.         sub(/^\/\/.*/, "", line) #remove C++ comments
  257.         while (match(line, /^"|^\/\*|^'/))
  258.             {
  259.             if (match(line, /^"/))
  260.                 {
  261.                 GetString()
  262.                 return
  263.                 }
  264.             else if (match(line, /^'/))
  265.                 {
  266.                 GetCharConstant()
  267.                 return
  268.                 }
  269.             else
  270.                 SkipComment()
  271.             sub(/^[ \t]+/, "", line)
  272.             sub(/^\/\/.*/, "", line)
  273.             }
  274.         } while (length(line) == 0 && getline line > 0);
  275.     if (length(line) == 0)
  276.         toktype = EOF
  277.     }
  278.  
  279. function GetString(        len, c, i, temp, esc)
  280.     {
  281.     
  282.     len = length(line)
  283.     i = 2;
  284.     for (esc = 0; i <= len; ++i)
  285.         {
  286.         c = substr(line, i, 1)
  287.         if (c == "\"")
  288.             {
  289.             if (esc == 0 || esc%2 == 0)
  290.                 {
  291.                 tok = temp substr(line,1,i)
  292.                 line = substr(line, i+1)
  293.                 toktype = STRING
  294.                 return;
  295.                 }
  296.             else
  297.                 esc = 0
  298.             }
  299.         else if (c == "\\")
  300.             {
  301.             if (i == len) #end of line, string continued
  302.                 {
  303.                 temp = temp substr(line,1,len-1)
  304.                 if (getline line <= 0)
  305.                     error("unterminated string")
  306.                 else
  307.                     {
  308.                     esc = 0
  309.                     i = 0
  310.                     len = length(line)
  311.                     if (len == 0)
  312.                         error("unterminated string")
  313.                     }
  314.                 }
  315.             else
  316.                 ++esc
  317.             }
  318.         else
  319.             esc = 0
  320.         }
  321.     error("unterminated string")
  322.     }
  323.  
  324. function GetCharConstant(        len, c, i, esc)
  325.     {
  326.     len = length(line)
  327.     i = 2;
  328.     toktype = CHAR_CONSTANT
  329.     for (esc = 0; i <= len; ++i)
  330.         {
  331.         c = substr(line, i, 1)
  332.         if (c == "'")
  333.             {
  334.             if (esc == 0 || esc%2 == 0)
  335.                 {
  336.                 tok = substr(line,1,i)
  337.                 line = substr(line, i+1)
  338.                 return;
  339.                 }
  340.             else
  341.                 esc = 0
  342.             }
  343.         else if (c == "\\")
  344.             ++esc
  345.         else
  346.             esc = 0
  347.         }
  348.     error("unterminated char constant")
  349.     }
  350.  
  351. function SkipComment(        len, c, i)
  352.     {
  353.     
  354.     i = 3;
  355.     do
  356.         {
  357.         for (len = length(line); i <= len; ++i)
  358.             {
  359.             c = substr(line, i, 2)
  360.             if (c == "*/")
  361.                 {
  362.                 line = substr(line, i+2)
  363.                 return;
  364.                 }
  365.             }
  366.         i = 1;
  367.         } while (getline line > 0);
  368.     error("unterminated comment")
  369.     }
  370.  
  371. function error(s)
  372.     {
  373.     print "Error:", s
  374.     print "Location:", filename, NR
  375.     print "Current Line:", line
  376.     print "Current token", tok
  377.     print "Current toktype:", toktype
  378.     exit 1
  379.     }